using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace BackyardBunnies
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        
        //Sprite Stuff
        SpriteBatch spriteBatch;
        SpriteManager spriteManager;

        //Music & Sounds
        Song backgroundMusic;


        //Background Images
        Texture2D splashScreen;
        Texture2D background;
        Texture2D endScreen;

        //Random
        public Random rnd { get; private set; }
        
        //Score
        int currentScore = 0;

        //Fonts
        SpriteFont scoreFont;
        SpriteFont endGameFont;
        SpriteFont timerFont;

        //Timer
        float timeElapsed;
        float startingTimeInSeconds = 60;
        int currentMinutes;
        int currentSeconds;
        int currentTime;
        float currentFloatTime;
        string correctSeconds;


        //Game State Stuff
        enum GameState { Start, InGame, GameOver };
        GameState currentState = GameState.Start;



        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            rnd = new Random();

            //Sets Screen to 800x600
            graphics.PreferredBackBufferHeight = 600;
            graphics.PreferredBackBufferWidth = 800;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // Use Sprite Manager
            spriteManager = new SpriteManager(this);
            Components.Add(spriteManager);

            // Used for Game States
            spriteManager.Enabled = false;
            spriteManager.Visible = false;
            
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // Load the Backgrounds
            background = Content.Load<Texture2D>(@"Images\Notepad");
            splashScreen = Content.Load<Texture2D>(@"Images\splashScreen");
            endScreen = Content.Load<Texture2D>(@"Images\endScreen");

            // Load the Fonts
            scoreFont = Content.Load<SpriteFont>(@"Fonts\TempusSansITC");
            endGameFont = Content.Load<SpriteFont>(@"Fonts\ComicSansMS");
            timerFont = Content.Load<SpriteFont>(@"Fonts\ComicSansMSBIG");

            //Load and Play the Music
            backgroundMusic = Content.Load<Song>(@"Audio\buddyHolly");
            MediaPlayer.Play(backgroundMusic);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            //Update the Current Game State
            switch (currentState)
            {
                case GameState.Start:
                    // GamePad State and Keyboard Enter start the game
                    if ((GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.Start)) ||
                        (Keyboard.GetState().IsKeyDown(Keys.Enter)))
                    {
                        currentState = GameState.InGame;
                        spriteManager.Enabled = true;
                        spriteManager.Visible = true;
                    }
                    break;
                case GameState.InGame:

                    UpdateTimer(gameTime);
                    //End the game if negative score
                    if (currentScore < 0)
                    {
                        currentScore = 0;
                        //currentState = GameState.GameOver;
                    }
                    
                    //End the game if timer runs out
                    else if ((currentMinutes == 0) && (currentSeconds == 0))
                    {
                        currentState = GameState.GameOver;
                    }

                    break;
                case GameState.GameOver:
                    GamePad.SetVibration(PlayerIndex.One, 0f, 0f);
                    spriteManager.Enabled = false;
                    spriteManager.Visible = false;
                    break;
            }
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            switch (currentState)
            {
                case GameState.Start:
                    // Draw the Splash Screen
                    GraphicsDevice.Clear(Color.White);
                    spriteBatch.Begin();
                    spriteBatch.Draw(splashScreen, Vector2.Zero, Color.White);
                    spriteBatch.End();
                    break;
                case GameState.InGame:
                    GraphicsDevice.Clear(Color.White);

                    spriteBatch.Begin();

                    //Draw the Background
                    spriteBatch.Draw(background, Vector2.Zero, Color.White);

                    //Draw the Score
                    spriteBatch.DrawString(scoreFont, "Score: " + currentScore,
                        new Vector2(630, 550), Color.SlateGray, 0, Vector2.Zero, 1,
                        SpriteEffects.None, 1);

                    spriteBatch.End();

                    DrawTimer();
                    break;
                case GameState.GameOver:
                    spriteBatch.Begin();

                    //Draw the End Screen
                    spriteBatch.Draw(endScreen, Vector2.Zero, Color.White);

                    //Draw the ending score
                    spriteBatch.DrawString(endGameFont, "Total Score: " + currentScore,
                        new Vector2(500, 250), Color.Blue, 0, Vector2.Zero, 1,
                        SpriteEffects.None, 1);

                    spriteBatch.End();
                    break;
            }

            base.Draw(gameTime);
        }

        //Used for changing the score
        public void AddScore(int score)
        {
            currentScore += score;
        }

        //Updates the timer based on current game time
        public void UpdateTimer(GameTime gameTime)
        {
            timeElapsed += (float)gameTime.ElapsedGameTime.TotalSeconds;
            currentFloatTime = startingTimeInSeconds - timeElapsed;

            currentTime = Convert.ToInt32(currentFloatTime);
            currentMinutes = currentTime / 60;
            currentSeconds = currentTime % 60;

            correctSeconds = currentSeconds.ToString("00");
        }

        //Draws the timer
        public void DrawTimer()
        {

            string showTimeLabel;
            if (currentSeconds >= 10)
                showTimeLabel = currentMinutes + ":" + currentSeconds;
            else
                showTimeLabel = currentMinutes + ":" + correctSeconds;

            spriteBatch.Begin();
            spriteBatch.DrawString(timerFont, showTimeLabel, new Vector2(350,0), Color.Red,
                0, Vector2.Zero, 1, SpriteEffects.None, 1);
            spriteBatch.End();
        }
    }
}
